
#include "dlk_frame.h"

/*********************************
the dlk_frame is the definition of DLK frame format
*********************************/

uint8_t addr_type_to_addr_len(uint8_t addr_type)
{
	if(addr_type == FRAME_LONG_ADDR){
		return FRAME_LONG_ADDR_LEN;
	}
	else if(addr_type == FRAME_SHORT_ADDR){
		return FRAME_SHORT_ADDR_LEN;
	}
	else{
		return 0XFF;
	}
}

uint8_t addr_len_to_addr_type(uint8_t addr_len)
{
	if(addr_len == FRAME_LONG_ADDR_LEN){
		return FRAME_LONG_ADDR;
	}
	else if(addr_len == FRAME_SHORT_ADDR_LEN){
		return FRAME_SHORT_ADDR;
	}
	else{
		return 0XFF;
	}
}


static uint8_t XOR_Check_Sum(uint8_t *dat,uint8_t length)
{
	uint8_t result;
	result = 0;
	for(; length > 0; length--)
	{
		result = result ^ *dat;
		dat++;
	}
	return result;
}

uint8_t deframe_is_encrypted(uint8_t* input_frame)
{
	FRAME_HEAD_BYTE_STRUCT* head =  &(input_frame[0]);
	return (head->encrypted);
}

uint8_t deframe_get_frame_count(uint8_t* input_frame)
{
	return input_frame[1];
}

uint8_t deframe(uint8_t* input_frame, uint8_t input_frame_len,
			FRAME_STRUCT* output_frame_struct,
			uint8_t* output_frame_playload,
			uint8_t* output_target_node_addr,
			uint8_t* output_source_node_addr)
{
	uint8_t frame_playload_pointer = 0;

	if(input_frame == 0){
	    return 0;
	}
	if(input_frame_len <
		FRAME_CONTROL_BYTE_LEN+
		FRAME_SHORT_ADDR_LEN+
		FRAME_SHORT_ADDR_LEN+
		FRAME_VERF_BYTE_LEN){
	    return 0;
	}
	if(output_frame_struct == 0){
	    return 0;
	}
	if(output_frame_playload == 0){
	    return 0;
	}
	if(output_target_node_addr == 0){
	    return 0;
	}
	if(output_source_node_addr == 0){
	    return 0;
	}

	*((uint8_t*)(&(output_frame_struct->head_byte))) = input_frame[0];

	if(input_frame[1] > FRAME_COUNT_MAX){
	    return 0;
	}
	output_frame_struct->frame_count = input_frame[1];

	if(input_frame[2] > FRAME_PAYLOAD_MAX_LEN){
	    return 0;
	}
	output_frame_struct->playload_len = input_frame[2];

	frame_playload_pointer += FRAME_CONTROL_BYTE_LEN;
	if(output_frame_struct->head_byte.target_addr_type == FRAME_SHORT_ADDR){
		memcpy(output_target_node_addr, &(input_frame[frame_playload_pointer]), FRAME_SHORT_ADDR_LEN);
		frame_playload_pointer += FRAME_SHORT_ADDR_LEN;
	}
	else{
		memcpy(output_target_node_addr, &(input_frame[frame_playload_pointer]), FRAME_LONG_ADDR_LEN);
		frame_playload_pointer += FRAME_LONG_ADDR_LEN;
	}

	if(output_frame_struct->head_byte.source_addr_type == FRAME_SHORT_ADDR){
		memcpy(output_source_node_addr, &(input_frame[frame_playload_pointer]), FRAME_SHORT_ADDR_LEN);
		frame_playload_pointer += FRAME_SHORT_ADDR_LEN;
	}
	else{
		memcpy(output_source_node_addr, &(input_frame[frame_playload_pointer]), FRAME_LONG_ADDR_LEN);
		frame_playload_pointer += FRAME_LONG_ADDR_LEN;
	}

	if(input_frame_len !=
		(output_frame_struct->playload_len)+frame_playload_pointer+FRAME_VERF_BYTE_LEN){
		return 0;
	}


//	temp1 = XOR_Check_Sum(input_frame, (output_frame_struct->playload_len)+frame_playload_pointer);
//	temp2 = input_frame[(output_frame_struct->playload_len)+frame_playload_pointer];
//	if(temp1 != temp2){
//		return 0;	
//	}

	if(XOR_Check_Sum(input_frame, (output_frame_struct->playload_len)+frame_playload_pointer)
		!= input_frame[(output_frame_struct->playload_len)+frame_playload_pointer]){
		return 0;
	}
	output_frame_struct->verf =
		input_frame[(output_frame_struct->playload_len)+frame_playload_pointer];

	memcpy(output_frame_playload, &(input_frame[frame_playload_pointer]), output_frame_struct->playload_len);

	return 1;
}

uint8_t framing(FRAME_STRUCT* input_frame_struct,
			uint8_t* input_frame_playload,
			uint8_t* input_target_node_addr,
			uint8_t* input_source_node_addr,
			uint8_t* output_frame, uint8_t* output_frame_len)
{
	uint8_t frame_playload_pointer = 0;

	if(input_frame_playload == 0){
	    return 0;
	}
	if(input_target_node_addr == 0){
	    return 0;
	}
	if(input_source_node_addr == 0){
	    return 0;
	}
	if(output_frame == 0){
	    return 0;
	}
	if(output_frame_len == 0){
	    return 0;
	}

	output_frame[0] = *(uint8_t*)(&(input_frame_struct->head_byte));

	if(input_frame_struct->frame_count > FRAME_COUNT_MAX){
	    return 0;
	}
	output_frame[1] = input_frame_struct->frame_count;

	if(input_frame_struct->playload_len > FRAME_PAYLOAD_MAX_LEN){
	    return 0;
	}
	output_frame[2] = input_frame_struct->playload_len;

	frame_playload_pointer += FRAME_CONTROL_BYTE_LEN;
	if(input_frame_struct->head_byte.target_addr_type == FRAME_SHORT_ADDR){
		memcpy(&(output_frame[frame_playload_pointer]), input_target_node_addr, FRAME_SHORT_ADDR_LEN);
		frame_playload_pointer += FRAME_SHORT_ADDR_LEN;
	}
	else{
		memcpy(&(output_frame[frame_playload_pointer]), input_target_node_addr, FRAME_LONG_ADDR_LEN);
		frame_playload_pointer += FRAME_LONG_ADDR_LEN;
	}

	if(input_frame_struct->head_byte.source_addr_type == FRAME_SHORT_ADDR){
		memcpy(&(output_frame[frame_playload_pointer]), input_source_node_addr, FRAME_SHORT_ADDR_LEN);
		frame_playload_pointer += FRAME_SHORT_ADDR_LEN;
	}
	else{
		memcpy(&(output_frame[frame_playload_pointer]), input_source_node_addr, FRAME_LONG_ADDR_LEN);
		frame_playload_pointer += FRAME_LONG_ADDR_LEN;
	}

	*output_frame_len =
		(input_frame_struct->playload_len)+frame_playload_pointer+FRAME_VERF_BYTE_LEN;

	memcpy(&(output_frame[frame_playload_pointer]), input_frame_playload,  input_frame_struct->playload_len);

	output_frame[(input_frame_struct->playload_len)+frame_playload_pointer] =
		XOR_Check_Sum(output_frame, (input_frame_struct->playload_len)+frame_playload_pointer);

	return 1;
}
